package com.wxxymakers.grademark.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wxxymakers.grademark.exception.ServiceException;
import com.wxxymakers.grademark.model.entity.WxIncident;
import com.wxxymakers.grademark.model.entity.WxItem;
import com.wxxymakers.grademark.model.entity.WxItemRecord;
import com.wxxymakers.grademark.model.mapper.WxItemRecordMapper;
import com.wxxymakers.grademark.utils.NumUtils;
import com.wxxymakers.grademark.utils.PageUtils;
import com.wxxymakers.grademark.utils.RecordMarkUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * @AUTHOR soft
 * @DATE 2018/12/29 23:36
 * @DESCRIBE
 */
@Service
public class WxItemRecordService {

    @Autowired
    private WxItemService itemService;

    @Autowired
    private WxItemRecordMapper recordMapper;

    @Autowired
    private WxIncidentService incidentService;

    /**
     * 校验事件有效区间是不是合理
     * 需要在beginTime被设置之后
     * @param record 记录
     * @return true or false
     */
    private boolean verifyRange(WxItemRecord record) {
        Date beginTime = record.getBeginTime();
        Date endTime   = record.getEndTime();

        WxIncident incident = incidentService.findOne(record.getIncidentId());
        if (incident != null) {
            record.setIncident(incident);

            if (beginTime != null) {
                if (beginTime.after(endTime)) { // 立项时间在结项时间之后
                    throw new ServiceException("立项结项时间有误！");
                }
                /*
                 满足三种情况之一即可
                 1、完全在区间内
                 2、结项时间在区间内
                 3、立项时间在区间内
                  */
                return (beginTime.after(incident.getBeginRange()) && beginTime.before(incident.getEndRange())) ||
                        (endTime.after(incident.getBeginRange()) && endTime.before(incident.getEndRange()));
            } else {
                return endTime.after(incident.getBeginRange())
                        && endTime.before(incident.getEndRange()); // 保证成果获得时间在区间内
            }
        }
        return false;
    }

    /**
     * 对记录进行统计
     * @param record 用户提交的记录信息
     */
    private void countRecord(WxItemRecord record) {
        WxItem item = itemService.byIdJoin(record.getItemId());
        if (StringUtils.isEmpty(record.getName())) { // 默认记录的项目名和item项目名一样
            record.setName(item.getName());
        }
        if (!item.getNeedEnd()) {
            record.setBeginTime(null);
        }
        record.setAudit(true); // 默认通过审核 是不是真的审核通过需要管理员在自己控制

        if (!verifyRange(record)) {
            throw new ServiceException("您填写的成果不在本次统计之内！");
        }
        /*
         * 不是自己写分数的需要自动统计分数
         */
        if (!item.getCanWrite()) {
            float score = RecordMarkUtils.mark(item, record); // 统计所得分数
            if (score <= 0) {
                throw new ServiceException("无效的成果记录！");
            }
            record.setScore(score);
        } else {
            if (Math.abs(record.getScore()) > Math.abs(item.getMaxScore())) {
                throw new ServiceException("填写的分数不符合要求！");
            }
            if (!item.getTisAdd() && record.getScore() > 0) { // 确保自填分数符合规定
                record.setScore(record.getScore() * -1);
            }
        }
    }

    @Transactional
    public boolean add(WxItemRecord record) {
        countRecord(record);
        record.setDatetime(new Date());

        return recordMapper.insert(record) > 0;
    }

    @Transactional
    public boolean delete(int id) {
        return recordMapper.deleteById(id) > 0;
    }

    @Transactional
    public boolean change(WxItemRecord record) {
        if (NumUtils.lteZero(record.getId())) {
            throw new ServiceException("id不存在，无法定位到被修改的记录");
        }
        countRecord(record);

        return recordMapper.updateById(record) > 0;
    }

    @Transactional
    public boolean adjust(WxItemRecord record) {
        if (NumUtils.lteZero(record.getId())) {
            throw new ServiceException("id不存在，无法定位到被修改的记录");
        }
        return recordMapper.updateById(record) > 0;
    }

    @Transactional
    public boolean audit(WxItemRecord record) {
        return recordMapper.updateById(record) > 0;
    }

    public WxItemRecord byId(int id) {
        return recordMapper.selectById(id);
    }

    /**
     * 可以根据部门id进行分页查询
     *
     * @param collegeId 学院id
     * @param deptId    部门id
     * @param un        用户名 模糊查询
     */
    public Page<WxItemRecord> page(int page, int limit, Integer collegeId, Integer deptId, String un, WxItemRecord query) {
        if (StringUtils.isEmpty(un)) {
            un = null;
        } else {
            un = "%" + un + "%";
        }
        long total = recordMapper.pageCount(collegeId, deptId, un, query);
        if (total > 0) {
            List<WxItemRecord> itemRecords = recordMapper.page((page - 1) * limit, limit, collegeId, deptId, un, query);
            return new PageImpl<>(itemRecords, new PageRequest(page - 1, limit), total);
        }
        return null;
    }

    public Page<WxItemRecord> page(int page, int limit, WxItemRecord query) {
        QueryWrapper<WxItemRecord> wrapper = new QueryWrapper<>(query);
        wrapper.orderByDesc("id");

        int total = recordMapper.selectCount(wrapper);
        if (total > 0) {
            List<WxItemRecord> itemRecords = recordMapper.selectPage(PageUtils.rowBounds(page, limit), wrapper).getRecords();
            return new PageImpl<>(itemRecords, new PageRequest(page - 1, limit), total);
        }
        return null;
    }

    /**
     * 根据事件id和学院id查询所有的记录
     * 没有就不作为条件
     * @param iid 事件id
     * @param collegeId 学院id
     */
    public List<WxItemRecord> list(Integer iid, Integer collegeId, Boolean audit) {
        WxItemRecord record = new WxItemRecord();
        record.setIncidentId(iid);
        record.setAudit(audit);
        return recordMapper.page(0, Integer.MAX_VALUE, collegeId, null, null, record);
    }


    /**
     * 根据事件和学院id进行统计记录参与人数
     * @param iid 事件id
     * @param collegeId 学院id
     */
    public long countByIIdAndCollegeId(Integer iid, Integer collegeId) {
        if (NumUtils.lteZero(collegeId)) {
            return recordMapper.countPeople(iid);
        }
        return recordMapper.countPeopleTwo(iid, collegeId);
    }

    /**
     * 设置记录为统计过
     * @param records 记录列表
     */
    @Transactional
    public void counted(List<WxItemRecord> records) {
        records.stream().filter(re -> "0".equals(re.getStatus()))
                .forEach(re -> recordMapper.updateStatus(re.getId(), "1"));
    }
}
